package com.wsoft.bpm.component.command;

import cn.hutool.core.collection.CollUtil;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.task.Task;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 使用Outgoing结合complete来实现跳转。好处是可以把数据处理交给工作流引擎
 *
 * @author zhonglj
 * @date 2024-11-11 15:47
 **/
@Log4j2
@AllArgsConstructor
public class OutgoingJumpMultiCmd implements Command<Boolean> {

    private String taskId;
    private List<String> targetNodes;

    @Override
    public Boolean execute(CommandContext commandContext) {
        if (CollUtil.isEmpty(targetNodes)) {
            log.error("目标节点为空!");
            return false;
        }

        TaskService taskService = commandContext.getProcessEngineConfiguration().getTaskService();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            log.error("当前任务不存在!");
            return false;
        }

        Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
        FlowElement currFlow = process.getFlowElement(task.getTaskDefinitionKey());
        List<SequenceFlow> newSequenceFlows = new ArrayList<>();
        for (String targetNode : targetNodes) {
            FlowElement toFlow = process.getFlowElement(targetNode);
            if (toFlow == null) {
                log.error("任务节点 {} 不存在!", targetNode);
                continue;
            }

            // 建立新方向
            SequenceFlow newSequenceFlow = new SequenceFlow();
            String uuid = UUID.randomUUID().toString().replace("-", "");
            newSequenceFlow.setId(uuid);
            // 来源节点
            newSequenceFlow.setSourceFlowElement(currFlow);
            // 目标节点
            newSequenceFlow.setTargetFlowElement(toFlow);
            newSequenceFlows.add(newSequenceFlow);
        }

        if (newSequenceFlows.isEmpty()) {
            log.error("目标节点为空!");
            return false;
        }

        // 备份原出口
        List<SequenceFlow> originOutgoing = ((FlowNode) currFlow).getOutgoingFlows();
        // 设置新出口
        ((FlowNode) currFlow).setOutgoingFlows(newSequenceFlows);
        // 完成任务
        taskService.complete(taskId);
        // 还原出口
        ((FlowNode) currFlow).setOutgoingFlows(originOutgoing);
        return true;
    }
}
